#include "SysDefine.hpp"
#include "MqttClient.hpp"
extern "C" { // 用cc编译的需要加extern C包含
    //#include "luckfox_gpio.h"
}

bool g_should_quit = false;


// 信号处理
void SigintHandler(int signum)
{
	switch (signum) {
    case SIGINT: // ctrl c
		case SIGQUIT: // ctrl '\'
		case SIGTSTP: // ctrl z
      g_should_quit = true;
			break;
	}
}


// zmq消息订阅测试
void* Thread_Test(void* arg)
{
	zmq::context_t ctx;
	zmq::socket_t pubSock(ctx, zmq::socket_type::pub);
	pubSock.bind(ZMQ_CAM_OUT_URL);

	while (1) {
		// LOG_ERR << "main send msg";
		// pubSock.send(zmq::str_buffer("AA"), zmq::send_flags::sndmore);
		// pubSock.send(zmq::str_buffer("Message in A envelope"));
		// pubSock.send(zmq::str_buffer("BB"), zmq::send_flags::sndmore);
		// pubSock.send(zmq::str_buffer("Message in B envelope"));
		// pubSock.send(zmq::str_buffer("CC"), zmq::send_flags::sndmore);
		// pubSock.send(zmq::str_buffer("Message in C envelope"));
		ThreadSleepMs(10000);
	}
}

// 推送照片数据到mqtt
void PushPhoto(string dirPath, string fileName, int bulkSize)
{
  string outName = "cap.jpg";
  string path = dirPath + "/" + fileName;

  LOG_DEBUG << "--->>> read file " << path;
  MqttClient::GetIns()->Publish("file-opt", outName, "remove");

  FILE *fd = fopen(path.c_str(), "rb");
  if (fd == nullptr) {
    printf("ERROR: open file: %s fail, exit\n", path.c_str());
    return;
  }

  int readCnt = 0;
  std::unique_ptr<char[]> ptr(new char[bulkSize]);
  do {
    readCnt = fread(ptr.get(), 1, bulkSize, fd);
    if (readCnt <= 0) {
      LOG_ERR << "read file error " << readCnt;
      return;
    }
    MqttClient::GetIns()->Publish("file", outName, ptr.get(), readCnt);
    LOG_DEBUG << ">>> Send " << readCnt << " bytes";
  } while (readCnt == bulkSize);
  fclose(fd); // 关闭文件

  MqttClient::GetIns()->Publish("file-opt", outName, "save");
}

// 调用拍照程序生成照片
int CameraOut(const char *outDir, const char *prefix, const char separator)
{
  string outStr;
  ExecuteShell("echo \"all=0\" > /tmp/rt_log_level", outStr); // 修改log等级

  stringstream cmd;
  cmd << "venc_jpeg -c 3 -n " << prefix << separator << " -o " << outDir;
  LOG_DEBUG << "[Cam] Cmd: " << cmd.str();
  uint retLen = ExecuteShell(cmd.str(), outStr); // 获取照片
  LOG_DEBUG << "[Cam] Cmd ret len " << retLen;
  return retLen;
}

// 读取照片目录
void ReadCameraDir(const char *dirPath, const char *prefix, const char separator)
{
	DIR* dir;
	struct dirent* dirEntry;
	dir = opendir(dirPath);
	if (dir == NULL) {
		LOG_ERR << "Cannot found camera out dir.";
		return;
	}
	while ((dirEntry = readdir(dir)) != NULL) { // 遍历目录
		string fileName(dirEntry->d_name);
		if (fileName == "." || fileName == "..") continue; // 去掉自己
		vector<string> fnVec = StrSplit(fileName, separator);
		if (fnVec.size() == 2 && strcmp(fnVec[0].data(), prefix) == 0) {
      PushPhoto(string(dirPath), fileName, 100000);
      break;
		}
	}
	closedir(dir);
}




const char *g_target = "/tmp/1.jpg";

// 命令行参数解析
void InputArgParse(int argc, char* argv[])
{
  int c;
	while ((c = getopt(argc, argv, "?::f:n")) != -1) {
		switch (c) {
      case 'n':
        //u32Height = atoi(optarg);
        break;
      case 'f':
        if (optarg) g_target = optarg;
        LOG_DEBUG << "f:" << optarg;
        break;
		}
	}
}

// 主函数
int main(int argc, char* argv[])
{
	LOG_INFO << "---------- Camera App Start ----------";
  InputArgParse(argc, argv);

	json js;
	js["name"] = "pi";
  js["pi"] = 3.141;
	LOG_DEBUG << "[ConnectMqttSrv] json test: " << js.dump();

  auto StartMs = GetSystemMs();
  //ThreadSleepMs(10*1000);
  LOG_INFO << "[Cam] Start running, now is " << (GetSystemMs() - StartMs);

	signal(SIGINT, SigintHandler); // 自定义ctrl c信号处理
	signal(SIGTSTP, SigintHandler); // 自定义ctrl z信号处理
  signal(SIGQUIT, SigintHandler); // 自定义ctrl \信号处理

  S_SET("dev-id", "270000006");
  S_SET("dev-key", "489827118");
  S_SET("topic-file-opt", StrJoin({"0", "dtu", "file-opt", "270000006"}, "/"));
  S_SET("topic-file", StrJoin({"0", "dtu", "file", "270000006"}, "/"));
  SETTINGS->Debug();

	// 定义zmq消息对象给mq线程用
	zmq::context_t ctx;
	zmq::socket_t pubSock(ctx, zmq::socket_type::pub);
	pubSock.bind(ZMQ_US_MSG_URL);

	// 启动mq连接
	MqttClient::GetIns()->ConnectMqttSrv(&pubSock);

  while (!g_should_quit) {
    auto retLen = CameraOut("/tmp", "cap", '-');
    if (retLen) {
      ReadCameraDir("/tmp", "cap", '-');
    }
    LOG_DEBUG << "[Cam] Finish!";
    sleep(5);
  }

	// 启动zmq消息发布线程
	//pthread_t pid_test;
	//pthread_create(&pid_test, NULL, &Thread_Test, NULL);

	LOG_DEBUG << "user app stop";
	return 0;
}